/*
 * CS_PVP_ROOM_LIST.cpp
 *
 *  Created on: 2014. 1. 6.
 *      Author: mega
 */

#include "../../User.h"
#include "../../Command.h"
#include "../../NLogic/Space.h"
#include "../../NLogic/Party.h"
#include "../../NLogic/Static.h"
#include "../../NResource/Static.h"

namespace ProjectZ { namespace NCommand {

static void SendFailPVPRoomList(User * pUser, int ack)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ack);
	pAck->MakePacket(CMD_SC_PVP_ROOM_LIST);
	pUser->Send(pAck);
}

void Command::CS_PVP_ROOM_LIST(User * pUser, ::Network::Packet * pPacket)
{
/*	CS_PVP_ROOM_LIST			0x1323
	{
	}

	SC_PVP_ROOM_LIST			0x1324
	{
		s16	ack;
		u16	u16room_count
		{
			u32	u32room_number;
			u8	u8player_count	(MAX:2)
			{
				u8	u8class_type;
				u16	u16level;
			}
		}
	}*/

	PREPARE_PACKET;

	NLogic::Space * pWorld = pUser->GetSpace();
	if (NULL == pWorld)
	{
		DEBUGLOG("%s : pWorld is NULL!", __FUNCTION__);
		SendFailPVPRoomList(pUser, ACK_NO_SPACE);
		return;
	}

	if (pWorld->GetData()._spaceType != NLogic::Space::SpaceType::WORLD)
	{
		DEBUGLOG("%s : User Space is Not WORLD!", __FUNCTION__);
		SendFailPVPRoomList(pUser, ACK_NO_SPACE);
		return;
	}

	if (pUser->GetEnumState() != User::EnumState::__NONE__)
	{
		DEBUGLOG("%s : User Status is Not Normal!!", __FUNCTION__);
		SendFailPVPRoomList(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	NResource::BattleMatchingResource::Flyweight * pFly =
			NResource::Static::InstancePtr()->GetBattleMatchingResource()->GetFly(NResource::BattleMatchingResource::BattleType::EM_BATTLE_TYPE_PVP);

	if (NULL == pFly)
	{
		DEBUGLOG("%s : pFly is NULL!", __FUNCTION__);
		SendFailPVPRoomList(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 오픈된 방 갯수 계산
	int openRoomcount = 0;
	std::vector<NLogic::Space *> clsPVPOpenRoomVector;

	NLogic::Static::SPACEVECTOR & clsPVPRoomVector = NLogic::Static::InstancePtr()->GETPVPROOMVECTOR();

	auto spaceIter = clsPVPRoomVector.begin();

	for (; spaceIter != clsPVPRoomVector.end(); ++spaceIter)
	{
		NLogic::Space * pSpace = ( * spaceIter );
		if (NULL == pSpace)
			continue;

		if (NULL == pSpace->GetPVPIndexer())
			continue;

		if (static_cast<int>(pSpace->GetUserTree().size()) >= 2)
			continue;

		NLogic::Party * pParty = pSpace->GetParty();
		if (NULL == pParty)
			continue;

		if (pParty->GetState() != NLogic::Party::State::NEW_PVP_ROOM_ACCEPT_WAIT)
			continue;

		if (NULL == pParty->GetMaster())
			continue;

		int masterLevel	= pParty->GetMaster()->GetCharacterInfo().level;
		int minLevel	= pUser->GetCharacterInfo().level + pFly->_MIN_LEVEL;
		int maxLevel	= pUser->GetCharacterInfo().level + pFly->_MAX_LEVEL;

		if (masterLevel < minLevel)
			continue;

		if (masterLevel > maxLevel)
			continue;

		clsPVPOpenRoomVector.push_back(pSpace);
		openRoomcount++;

		// 오픈된 방은 최대 99개만 노출한다
		if (99 <= openRoomcount)
			break;
	}

	// 응답
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

	*pAck << static_cast<int16_t>(ACK_OK);
	*pAck << static_cast<uint16_t>(clsPVPOpenRoomVector.size());

	std::for_each(clsPVPOpenRoomVector.begin(), clsPVPOpenRoomVector.end(), [&](NLogic::Space * pOpenPVPSpace) {

		NLogic::IndexerPVP * pPVPIndex = pOpenPVPSpace->GetPVPIndexer();
		*pAck << static_cast<uint32_t>(pPVPIndex->GetIndex());

		auto userTree = pOpenPVPSpace->GetUserTree();
		*pAck << static_cast<uint8_t>(userTree.size());

		std::for_each(userTree.begin(), userTree.end(), [&](NLogic::Space::USERTREE::value_type & pair) {
			User * pUser = pair.second;

			*pAck << static_cast<uint8_t>(pUser->GetCharacterInfo().classtype);
			*pAck << static_cast<uint16_t>(pUser->GetCharacterInfo().level);
		});

	} );

	pAck->MakePacket(CMD_SC_PVP_ROOM_LIST);
	pUser->Send(pAck);
	clsPVPOpenRoomVector.clear();
}

} /*NCommand*/ } /*ProjectZ*/
